/*
 *  AMPImgAssignmentDlgObserver.cpp
 *  AMPlugin
 *
 *  Created by Vu Tiet on 8/13/12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */


#include "VCPlugInHeaders.h"

// Implementation includes
#include "widgetid.h"

// Interface includes
#include "ISubject.h"
#include "IControlView.h"
#include "ITreeViewController.h"
#include "IPanelControlData.h"
#include "IWidgetParent.h"
#include "IStringListData.h"
#include "ITreeViewHierarchyAdapter.h"
#include "ITreeViewMgr.h"

// Interface includes:
#include "ISession.h"
#include "IApplication.h"
#include "IDialogMgr.h"
#include "IDialog.h"

// General includes:
#include "CoreResTypes.h"
#include "LocaleSetting.h"
#include "RsrcSpec.h"
#include "SelectionObserver.h"
#include "CDialogObserver.h"
#include "ITextControlData.h"


// Implem includes
#include "CObserver.h"
#include "K2Vector.tpp" // For NodeIDList to compile
#include "AMPStoryNodeID.h"
#include "AMPID.h"
#include "AMGlobal.h"
#include "JSONHelper.h"
#include <iostream>
using namespace std;

/**
 
 
 */

class AMPImgAssignmentDlgObserver : public CDialogObserver
	{
	public:
		
		/**
		 @param interface ptr from boss object on which this interface is aggregated.
		 */
		AMPImgAssignmentDlgObserver(IPMUnknown *boss);
		
		/**
		 Destructor for AMPListBoxObserver class
		 
		 */	
		~AMPImgAssignmentDlgObserver();
		
		/**
		 AutoAttach is only called for registered observers
		 of widgets.  This method is called by the application
		 core when the widget is shown.
		 
		 */	
		virtual void AutoAttach();
		
		/**
		 AutoDetach is only called for registered observers
		 of widgets. Called when widget hidden.
		 */	
		virtual void AutoDetach();
		
		/**
		 This class is interested in changes along IID_ILISTCONTROLDATA protocol with classID of
		 kListSelectionChangedMessage. This message is sent when a user clicks on an element
		 in the list-box.
		 
		 
		 @param theChange this is specified by the agent of change; it can be the class ID of the agent,
		 or it may be some specialised message ID.
		 @param theSubject this provides a reference to the object which has changed; in this case, the button
		 widget boss object that is being observed.
		 @param protocol the protocol along which the change occurred.
		 @param changedBy this can be used to provide additional information about the change or a reference
		 to the boss object that caused the change.
		 */	
		virtual void Update(const ClassID& theChange, ISubject* theSubject, const PMIID &protocol, void* changedBy);
		
		//RangeProgressBar *ProgressBar;
		//int32			  ProgressCount;
		
		//void DoOpenDialog(int32 nTypeDialog);
		void RefreshTreeView();
		void DoCloseDialog();
		void DeselectStories();

	};

CREATE_PMINTERFACE(AMPImgAssignmentDlgObserver, kAMPImgAssignmentDlgObserverImpl)

AMPImgAssignmentDlgObserver::AMPImgAssignmentDlgObserver(IPMUnknown* boss)
: CDialogObserver(boss)
{
	//printf("AMPImgAssignmentDlgObserver::AMPImgAssignmentDlgObserver \n");
}


AMPImgAssignmentDlgObserver::~AMPImgAssignmentDlgObserver()
{
	
}


void AMPImgAssignmentDlgObserver::AutoAttach()
{
	do {
		InterfacePtr<ISubject> subject(this, UseDefaultIID());
		if (subject != nil)
		{
			subject->AttachObserver(this, IID_ITREEVIEWCONTROLLER);
			// Get the IPanelControlData interface for the dialog:
			InterfacePtr<IPanelControlData> panelControlData(this, UseDefaultIID());
			if (panelControlData == nil)
			{
				ASSERT_FAIL("AMPIssuesDlgObserver::AutoAttach() panelControlData invalid");
				break;
			}
			
			// Attach to other widgets you want to handle dynamically here.
			AttachToWidget(kAMPAssignButtonWidgetID, IID_IBOOLEANCONTROLDATA, panelControlData);
			
			AttachToWidget(kAMPExitIssueButtonWidgetID, IID_IBOOLEANCONTROLDATA, panelControlData);
			
			
		}
	} while(kFalse);
}


void AMPImgAssignmentDlgObserver::AutoDetach()
{

	do {
		InterfacePtr<ISubject> subject(this, UseDefaultIID());
		if (subject != nil)
		{
			subject->DetachObserver(this, IID_ITREEVIEWCONTROLLER);
			
			InterfacePtr<IPanelControlData> panelControlData(this, UseDefaultIID());
			if (panelControlData == nil)
			{
				ASSERT_FAIL("AMPIssuesDlgObserver::AutoDetach() panelControlData invalid");
				break;
			}
			
			// Detach from other widgets you handle dynamically here.
			DetachFromWidget(kAMPAssignButtonWidgetID, IID_IBOOLEANCONTROLDATA, panelControlData);
			
			DetachFromWidget(kAMPExitIssueButtonWidgetID, IID_IBOOLEANCONTROLDATA, panelControlData);
			
		}
	} while (kFalse);
	
}


void AMPImgAssignmentDlgObserver::Update
(
 const ClassID& theChange, 
 ISubject* theSubject, 
 const PMIID &protocol, 
 void* changedBy
)
{
	//cout << "+++++++++++ AMPImgAssignmentDlgObserver::Update ++++++++++++" << endl;
	// Call the base class Update function so that default behavior will still occur (OK and Cancel buttons, etc.).
	//CDialogObserver::Update(theChange, theSubject, protocol, changedBy);
	
	do {
		if ((protocol == IID_ITREEVIEWCONTROLLER) && (theChange == kListSelectionChangedMessage) ) {
			//cout << "item selected" << endl;
			InterfacePtr<ITreeViewController> 	controller(this, UseDefaultIID());
			ASSERT(controller);
			if(!controller)
			{
				break;
			}
			PMString item;
			//bool16   casesensitive;
			NodeIDList selectedItems;
			controller->GetSelectedItems(selectedItems);
			
			const int kSelectionLength =  selectedItems.size() ;
			if (kSelectionLength> 0 )
			{
				K2Vector<NodeID>::const_iterator iter, startIter, endIter;
				startIter = selectedItems.begin();
				endIter = selectedItems.end();
				for(iter = startIter; iter != endIter; ++iter)
				{
					const AMPStoryNodeID* oneNode = static_cast<const AMPStoryNodeID*>(iter->Get());
					//item = oneNode->GetName();
					item = oneNode->GetId();
					item.Translate();
				}
				//cout << "item: " << item.GrabCString() << endl;
				g_ChosenStoryID = item.GrabCString();
				//cout << "g_ChosenStoryID: " << g_ChosenStoryID << endl;
				RefreshTreeView();
				
				// enable "Assign" button 
				InterfacePtr<IWidgetParent> 
				iWidgetParent(this, UseDefaultIID());
				ASSERT(iWidgetParent);
				if(!iWidgetParent)
				{
					break;
				}
				InterfacePtr<IPanelControlData>	iPanelControlData( 
																  (IPanelControlData*)iWidgetParent->QueryParentFor(IID_IPANELCONTROLDATA) );
				
				ASSERT(iPanelControlData);
				if(!iPanelControlData)
				{
					break;
				}
				
				IControlView* iWidgetView = 
				iPanelControlData->FindWidget(kAMPAssignButtonWidgetID);
				ASSERT(iWidgetView);
				if(!iWidgetView) {
					break;
				}
				iWidgetView->Enable(kTrue, kTrue);
			}
			else {
				
				// disable "Assign" button 
				if (g_ChosenStoryID.length() > 0) {
					break;
				}
				
				InterfacePtr<IWidgetParent> 
				iWidgetParent(this, UseDefaultIID());
				ASSERT(iWidgetParent);
				if(!iWidgetParent)
				{
					break;
				}
				InterfacePtr<IPanelControlData>	iPanelControlData( 
																  (IPanelControlData*)iWidgetParent->QueryParentFor(IID_IPANELCONTROLDATA) );
				
				ASSERT(iPanelControlData);
				if(!iPanelControlData)
				{
					break;
				}
				
				IControlView* iWidgetView = 
				iPanelControlData->FindWidget(kAMPAssignButtonWidgetID);
				ASSERT(iWidgetView);
				if(!iWidgetView) {
					break;
				}
				iWidgetView->Disable(kTrue);
				
			}
			
		}
		else {
			//cout << "button clicked" << endl;
			InterfacePtr<IControlView> controlView(theSubject, UseDefaultIID());
			if (controlView == nil)
			{
				ASSERT_FAIL("AMPIssuesDlgObserver::Update() controlView invalid");
				cout << "controlView is nil" << endl;
				break;
			}
			WidgetID theSelectedWidget = controlView->GetWidgetID();
			//cout << "theSelectedWidget - kOKButtonWidgetID: " << theSelectedWidget.Get() << " - " << kOKButtonWidgetID << endl;
			if (theSelectedWidget == kAMPExitIssueButtonWidgetID && theChange == kTrueStateMessage)
			{  
				// close dialog
				//cout << "exit button did click" << endl;
				DeselectStories();
				DoCloseDialog();
				
			}
			else if (theSelectedWidget == kAMPAssignButtonWidgetID && theChange == kTrueStateMessage) {
				InterfacePtr<IPanelControlData> panelData(this, UseDefaultIID());	
				// Don't assert, fail silently, the tree view panel may be closed.
				if(panelData == nil)
				{
					break;
				}
				
				IControlView* textboxWidget = panelData->FindWidget(kAMPImgCaptionEditTextWidgetID);
				ASSERT(textboxWidget);
				if(textboxWidget == nil)
				{
					break;
				}
				
				InterfacePtr<ITextControlData>	textControlData( textboxWidget, UseDefaultIID() );
				ASSERT(textControlData);
				if( textControlData== nil) {
					break;
				}
				PMString imgCaptionPMS(textControlData->GetString());
				

				//cout << "assign button did click" << endl;
				bool shouldAdd = TRUE;
				for (int i = 0; i < g_ImageInfo.size(); i++) {
					images_t curImgInfo = g_ImageInfo[i];
					if (curImgInfo.image_path.compare(g_ChosenImagePath) == 0) {
						shouldAdd = FALSE;
						curImgInfo.image_name = g_ChosenImageName;
						curImgInfo.story_id = g_ChosenStoryID;
						curImgInfo.image_caption = imgCaptionPMS.GrabCString();
						//cout << "curImgInfo.story_id: " << curImgInfo.story_id << endl;
						if (curImgInfo.image_status.compare("added") != 0) {
							curImgInfo.image_status = "update";
						}
						
						// re-assign 
						g_ImageInfo[i] = curImgInfo;
						break;
					}
				}
				if (shouldAdd == TRUE) {
					images_t addedImgInfo;
					addedImgInfo.image_path = g_ChosenImagePath;
					addedImgInfo.image_name = g_ChosenImageName;
					addedImgInfo.image_status = "added";
					addedImgInfo.story_id = g_ChosenStoryID;
					addedImgInfo.image_caption = imgCaptionPMS.GrabCString();
					g_ImageInfo.push_back(addedImgInfo);
				}
				
				
				/*
				for (int j = 0; j < g_ImageInfo.size(); j++) {
					images_t jImgInfo = g_ImageInfo[j];
					cout << "============" << endl;
					cout << "image path: " << jImgInfo.image_path << endl;
					cout << "image name: " << jImgInfo.image_name << endl;
					cout << "image status: " << jImgInfo.image_status << endl;
					cout << "story_id:" << jImgInfo.story_id << endl;
					cout << "image caption: " << jImgInfo.image_caption << endl;
					cout << "############" << endl;
				}
				
				string imageMap = JSONHelper::imagesMapString();
				cout << "imageMap: " << imageMap << endl;
				 */
				
				// reset tree view
				DeselectStories();
				DoCloseDialog();
			} // end assign button click
			
		}

	} while(0);
}


void AMPImgAssignmentDlgObserver::RefreshTreeView()
{
	do
	{
		
		InterfacePtr<IPanelControlData> panelData(this, UseDefaultIID());	
		// Don't assert, fail silently, the tree view panel may be closed.
		if(panelData == nil)
		{
			break;
		}
		
		IControlView* treeWidget = panelData->FindWidget(kAMPStoryTreeViewWidgetID);
		ASSERT(treeWidget);
		if(treeWidget == nil)
		{
			break;
		}
		
		
		// create new data list
		InterfacePtr<ITreeViewHierarchyAdapter> model(treeWidget, UseDefaultIID());
		ASSERT(model);
		if(!model) {
			break;
		}
				
		K2Vector<PMString> lists;
		/*
		PMString name1("so1|Story so 1");
		name1.Translate();
		lists.push_back(name1);
		
		PMString name2("so2|Story so 2");
		name2.Translate();
		lists.push_back(name2);
		
		PMString name3("so3|Story so 3");
		name3.Translate();
		lists.push_back(name3);
		*/
		for (int i = 0; i < g_TextFrameCount; i++) {
			//string listItem = g_TextFrames[i].storyID + "|" + g_TextFrames[i].storyName;
			string listItem = g_TextFrames[i].storyID;
			PMString itemPMS(listItem.c_str());
			itemPMS.Translate();
			lists.push_back(itemPMS);
		}
		
		InterfacePtr<IStringListData> iListData(model, IID_ISTRINGLISTDATA);
		iListData->SetStringList(lists);
		
		// redraw UI
		InterfacePtr<ITreeViewMgr> treeMgr(treeWidget, UseDefaultIID());
		
		treeMgr->ClearTree();
		treeMgr->ChangeRoot(kTrue);
		
	} while(kFalse);
}


void AMPImgAssignmentDlgObserver::DoCloseDialog() {
	do
	{
		// Get the application interface and the DialogMgr.
		InterfacePtr<IApplication> application(GetExecutionContextSession()->QueryApplication());
		if (application == nil)
		{
			ASSERT_FAIL("AMPIssuesDlgObserver::DoDialog: application invalid");
			break;
		}
		InterfacePtr<IDialogMgr> dialogMgr(application, UseDefaultIID());
		if (dialogMgr == nil)
		{ 
			ASSERT_FAIL("AMPIssuesDlgObserver::DoDialog: dialogMgr invalid"); 
			break;
		}
		
		InterfacePtr<IWidgetParent> iWidgetParent(this, UseDefaultIID());
		if(!iWidgetParent)
			break;
		
		InterfacePtr<IDialog> iDialog((IDialog *) iWidgetParent->QueryParentFor(IID_IDIALOG));
		iDialog->Close();
	} while (false);	
}


void AMPImgAssignmentDlgObserver::DeselectStories() {
	do {
		InterfacePtr<IPanelControlData> panelData(this, UseDefaultIID());	
		// Don't assert, fail silently, the tree view panel may be closed.
		if(panelData == nil)
		{
			break;
		}
		
		IControlView* treeWidget = panelData->FindWidget(kAMPStoryTreeViewWidgetID);
		ASSERT(treeWidget);
		if(treeWidget == nil)
		{
			break;
		}
		
		InterfacePtr<ITreeViewController> 	controller(treeWidget, UseDefaultIID());
		ASSERT(controller);
		if(!controller)
		{
			cout << "ITreeViewController is nil" << endl;
			break;
		}
		controller->DeselectAll();
	}while(kFalse);
}
